

from sympy.printing.str import StrPrinter
from sympy.printing.precedence import precedence, PRECEDENCE
from sympy.core.basic import S
from sympy.core.numbers import One, Rational
from sympy.core.power import Pow
from sympy.core.symbol import Symbol, Wild
from sympy.core.basic import Basic

import sympy.mpmath.libmp as mlib
from sympy.mpmath.libmp import prec_to_dps



class OpenclPrinter(StrPrinter):
    def __init__(self, profile={}):
        StrPrinter.__init__(self)
        if self._settings is None:
            _settings = {}
        self._settings.update(profile)
        if 'symbol_default_index' not in self._settings:
            self._settings['symbol_default_index'] = {}
    def _print_Integer(self, expr):
        return self._print(expr.p) + '.0f'
    def _print_NegativeOne(self, expr):
        return "-1.0f"
    def _print_One(self, expr):
        return "1.0f"
    def _print_Zero(self, expr):
        return "0.0f"
    def _print_Real(self, expr):
        prec = expr._prec
        if prec < 5:
            dps = 0
        else:
            dps = prec_to_dps(expr._prec)
        if self._settings["full_prec"] == True:
            strip = False
        elif self._settings["full_prec"] == False:
            strip = True
        elif self._settings["full_prec"] == "auto":
            strip = self._print_level > 1
        
        
        number_string_to_print = mlib.to_str(expr._mpf_, dps, strip_zeros=strip)
        if ('.' not in number_string_to_print):
            number_string_to_print += '.0'
        if (number_string_to_print[-1] != 'f'):
            number_string_to_print += 'f'
        return number_string_to_print
#    def _print_Rational(self, expr): #Todo: need to test before we insert this
#        #return '%s/%s'%(expr.p, expr.q)
#        return expr.p/expr.q # put .0f at the end if it doesn't have.
    
    def _print_Symbol(self, expr):
        if expr in self._settings['symbol_default_index']:
            return expr.name + '[' + str(self._settings['symbol_default_index'][expr]) + ']'
        else:
            return expr.name
    def _print_Pow(self, expr):
        PREC = precedence(expr)
        if expr.exp is S.NegativeOne:
            return '1 / %s' % (self.parenthesize(expr.base, PREC))
        elif expr.exp == 2:
            return '%s * %s' % (self.parenthesize(expr.base, PREC),
                            self.parenthesize(expr.base, PREC))
#        elif expr.exp == -2:
#            return '1/(%s*%s)' % (self.parenthesize(expr.base, PREC),
#                            self.parenthesize(expr.base, PREC)) #Todo: do we need this?
        elif expr.exp == 0.5:
            return 'sqrt(%s)' % (self.parenthesize(expr.base, PREC))
        else:
            return 'pow(%s, %s)' % (self.parenthesize(expr.base, PREC),
                             self.parenthesize(expr.exp, PREC))
if __name__ == '__main__':
    x = Symbol('x')
    op = OpenclPrinter({'symbol_default_index':{x:'gid0'}})
    print op.doprint(x ** 2 + x ** 2.0 + x ** 99 + x ** x + x ** (-2))
    print op.doprint(x ** (0.5))
    print op.doprint(x + 1 + (-1) + 4.0 + x)
